/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * Licensed under Simplified BSD License
 *
 *  
 * @Original Author: jin Chen
 * @date: Apr 21, 2005$
 * @version: 1.0
 */
package edu.psu.geovista.app.dataloader.v1.xml;

import edu.psu.geovista.app.dataloader.v1.components.PcpDataLoader;
import edu.psu.geovista.app.dataloader.v1.config.model.*;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.*;



public class PathsToDom4j {
    enum PathsXml{ Project, PcpData,TsData,ShapeData,Paths,Path,SelectedAttributes,Attr,
                   ID,time,projected,load,name,value

    }
    /*******************************************************************************************************
     *                load data
     *******************************************************************************************************/
    public static void  loadProject(Project proj, Document doc){
        Element root = doc.getRootElement(); //project
        String id = root.attributeValue(PathsXml.ID.toString());//"ID"
        String time = root.attributeValue(PathsXml.time.toString());

        Element pcpElmt = (Element) root.selectSingleNode(PathsXml.PcpData.toString()); //pcpdata
        Element tsElmt = (Element) root.selectSingleNode(PathsXml.TsData.toString()); //"tsdata"
        Element shpElmt = (Element) root.selectSingleNode(PathsXml.ShapeData.toString());//"shpdata"

        proj.setID(id);
        proj.setTime(time);
        System.out.println(PathsToDom4j.class.getName() +" loadPcpData -->");
        loadPcpData(proj.getPcpdata() ,pcpElmt);
        System.out.println(PathsToDom4j.class.getName() +" loadShapedata -->");
        loadShapedata(proj.getPcpdata() ,shpElmt);//for now, still put shp data information in pcpdata
        System.out.println(PathsToDom4j.class.getName() +" loadData -->");
        loadData(proj.getTsdata(),tsElmt);

    }


    private  static void loadPcpData (Pcpdata data,Element dataElmt){
        loadData(data,dataElmt);

       /* String project = dataElmt.attributeValue("projected");
        data.setShapeProjected(Boolean.valueOf(project) );*/


    }
    private  static void loadData (VariableData data,Element dataElmt){
        String load = dataElmt.attributeValue(PathsXml.load.toString());
        data.setLoad(Boolean.valueOf(load));
         System.out.println(PathsToDom4j.class.getName() +" loadAttrs -->");
        loadAttrs(data,dataElmt);
        System.out.println(PathsToDom4j.class.getName() +" loadPaths -->");
        loadPaths(data,dataElmt);

    }
    private static void loadShapedata(Pcpdata data,Element dataElmt){
        loadPaths(data,dataElmt);
        String project = dataElmt.attributeValue(PathsXml.projected.toString());
        data.setShapeProjected(Boolean.valueOf(project) );
    }
    public static void loadAttrs(VariableData data,Element dataElmt){
        List<String> attrlist = new ArrayList<String>();
        List list = dataElmt.selectNodes(PathsXml.SelectedAttributes.toString()+"/"+PathsXml.Attr.toString());
        //List list = selectElmt.elements(PathsXml.Attr.toString());
        Set attrs=new HashSet <String> ();
        for (Iterator iterator = list.iterator(); iterator.hasNext();) {
            Element attr = (Element) iterator.next();
            String name = attr.attributeValue(PathsXml.name.toString());
            attrs.add(name);
        }
        attrlist.addAll(attrs);
        data.setSelectedVariableNames(attrlist);

    }
    public static void loadPaths(VariableData data,Element dataElmt){

        
        List pathlist = dataElmt.selectNodes(PathsXml.Paths.toString()+"/"+PathsXml.Path.toString());
       //  System.out.println(PathsToDom4j.class.getName() +" loadPaths() loop -->");
        for (Iterator iterator = pathlist.iterator(); iterator.hasNext();) {
            Element pathElmt = (Element) iterator.next();
            String id = pathElmt.attributeValue(PathsXml.ID.toString());
            String value = pathElmt.attributeValue(PathsXml.value.toString());
            System.out.println(" "+value);
                                              
            List paths = data.getPaths();
            paths.add(new DfPath(id,value));

        }
        System.out.println(PathsToDom4j.class.getName() +"<-- loadPaths() loop");

    }
    /*******************************************************************************************************
     *                save
     *******************************************************************************************************/
    /**
     * save a project to a Document. Assume each doc contain only one project
     * @param proj
     * @return
     */
    public static Document convert(Project proj){
        edu.psu.geovista.app.dataloader.v1.config.model.Pcpdata pcp = proj.getPcpdata();
        edu.psu.geovista.app.dataloader.v1.config.model.TimeSeriesData tsdata = proj.getTsdata();
        String id = proj.getID();
        String time = proj.getTime();

        
        Document document = DocumentHelper.createDocument();
        //project
        Element projElmt = document.addElement(PathsXml.Project.toString());
        projElmt.addAttribute(PathsXml.ID.toString(),id);
        projElmt.addAttribute(PathsXml.time.toString(),time);

        //pcp
        Element pcpElmt = projElmt.addElement(PathsXml.PcpData.toString());
        setData(pcp,pcpElmt);

        //time series
        Element tsElmt = projElmt.addElement(PathsXml.TsData.toString());
        setData(tsdata,tsElmt);

        
         //shp data
        Element shpElmt = projElmt.addElement(PathsXml.ShapeData.toString());
        setShapeData(pcp,shpElmt);

        return document;
    }

    public static void setPcpData(Pcpdata pcp,Element dataElmt){
        setData(pcp,dataElmt);

        boolean shapeProjected = pcp.isShapeProjected();
        dataElmt.addAttribute(PathsXml.projected.toString(),Boolean.toString(shapeProjected));

    }
     public static void setShapeData(Pcpdata pcp,Element dataElmt){

        boolean shapeProjected = pcp.isShapeProjected();
        dataElmt.addAttribute(PathsXml.projected.toString(),Boolean.toString(shapeProjected));

        String shapeFile = pcp.getPath(PcpDataLoader.ShapeFile).getValue();//.getProperty(PcpDataLoader.ShapeFile);
        Element pathsElmt=dataElmt.addElement(PathsXml.Paths.toString());//can support loading multiple shape data
        createPath(pathsElmt,PcpDataLoader.ShapeFile,shapeFile); //for now, only add one path for the default shape file

     }
    /**************************************************
     *                data
     ***************************************************/
    public static void setData(VariableData data, Element dataElmt){
        List paths = data.getPaths();
        List<String> selectedAttributes = data.getSelectedVariableNames();
        boolean load = data.isLoad();
        //set load
        dataElmt.addAttribute(PathsXml.load.toString(),Boolean.toString(load) );
        //set paths
        Element pathsElmt = dataElmt.addElement(PathsXml.Paths.toString());
        /*Set<Object> keys = paths.keySet();
        for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
            String  id = (String) iterator.next();
            String value = paths.getProperty(id);
            if(! id.equals(PcpDataLoader.ShapeFile) ) {   //put shape data in shpdata
            createPath(pathsElmt,id,value);
            }
        }*/
        for (Iterator iterator = paths.iterator(); iterator.hasNext();) {
            Path path = (Path) iterator.next();
            String name = path.getName();
            String value = path.getValue();
            if(!name.equals(PcpDataLoader.ShapeFile) ) {   //put shape data in shpdata
                createPath(pathsElmt,name,value);
            }
        }

        //set selected attributes
        Element attrs = dataElmt.addElement(PathsXml.SelectedAttributes.toString());
        for (Iterator iterator = selectedAttributes.iterator(); iterator.hasNext();) {
            String attrname = (String) iterator.next();
            createAttribute(attrs,attrname);
        }


    }

    /**
     * create path element for paths
     * @param parent
     * @param id
     * @param value
     * @return
     */
    private  static Element createPath(Element parent,String id,String value){
        Element path=parent.addElement(PathsXml.Path.toString());
        path.addAttribute(PathsXml.ID.toString(),id);
        path.addAttribute(PathsXml.value.toString(),value);
        return path;
    }

    private static Element createAttribute(Element parent,String name){
        Element attr=parent.addElement(PathsXml.Attr.toString());
        attr.addAttribute(PathsXml.name.toString(),name);

        return attr;
    }
    /*******************************************************************************************************
     *                test
     *******************************************************************************************************/
    public static void main(String[] args) {


    }


}
